package cn.getech.data.development.utils.oozie;

import cn.getech.data.development.constant.JobType;
import cn.getech.data.development.dto.JobInfoDto;
import cn.getech.data.development.dto.JobNodeInfoDto;
import cn.getech.data.development.dto.JobNodeLayConfigDto;
import cn.getech.data.development.entity.JobNodeConfig;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.oozie.fluentjob.api.action.ErrorHandler;
import org.apache.oozie.fluentjob.api.action.ShellAction;
import org.apache.oozie.fluentjob.api.action.ShellActionBuilder;
import org.apache.oozie.fluentjob.api.factory.WorkflowFactory;
import org.apache.oozie.fluentjob.api.workflow.Workflow;
import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;

import java.util.*;
import java.util.stream.Collectors;

public class WorkFlowUtil implements WorkflowFactory {
    @Override
    public Workflow create() {
        return null;
    }

    /**
     * 生成workflow.xml文件
     *
     * @param nodeName
     * @param dependence
     * @param jobId
     * @param startKey
     * @return
     */
    public Workflow creatShell(Map nodeName, List dependence, String jobId, String startKey, Boolean isCoordinatorJob) {
        Map<String, ShellAction> actionMap = new HashMap<>();

//        ShellActionBuilder actionBuilder = ShellActionBuilder.create()
//                .withName("rest")
//                .withExecutable("${EXEC0}")
//                .withFile("${nameNode}/${rootDir}/${EXEC0}#${EXEC0}");

        ShellActionBuilder startBuilder = ShellActionBuilder.create()
                .withName(nodeName.get(startKey).toString() + startKey.replace("-", ""))
                .withResourceManager("${resourceManager}")
                .withNameNode("${nameNode}")
                .withConfigProperty("mapred.job.queue.name", "${queueName}")
                .withExecutable("${EXEC" + startKey.replace("-", "") + "}")
                .withFile("${nameNode}/${rootDir}/${EXEC" + startKey.replace("-", "") + "}#${EXEC" + startKey.replace("-", "") + "}")
                .withCaptureOutput(true);
//        if(isCoordinatorJob)
//            startBuilder.withErrorHandler(ErrorHandler.buildAsErrorHandler(actionBuilder));
//        else
        startBuilder.withoutErrorHandler();
        ShellAction shellAction = startBuilder.build();
        actionMap.put(startKey, shellAction);

        //存放每个节点的父节点集合
        Map dependence2 = new LinkedHashMap();
        dependence.forEach(d -> {
            JSONObject jsonObject = JSONObject.parseObject(d.toString());
            if (dependence2.containsKey(jsonObject.getString("to"))) {
                List fromNodes = (List) dependence2.get(jsonObject.getString("to"));
                fromNodes.add(jsonObject.getString("from"));
                dependence2.put(jsonObject.getString("to"), fromNodes);
            } else {
                List fromNodes = new ArrayList();
                fromNodes.add(jsonObject.getString("from"));
                dependence2.put(jsonObject.getString("to"), fromNodes);
            }
        });
        //生成每个节点action
        while (actionMap.size() != dependence2.size() + 1) {
            for (Object d : dependence) {
                JSONObject jsonObject = JSONObject.parseObject(d.toString());
                List fromNodes = (List) dependence2.get(jsonObject.getString("to"));
                Boolean flag = true;
                //判断该节点的所有父节点是否都已经生成action，没有就返回false
                for (Object f : fromNodes) {
                    if (!actionMap.containsKey(f)) {
                        flag = false;
                    }
                }
                //生成 action 的前提是所有父节点都已经生成，且该节点未曾生成
                if (flag && !actionMap.containsKey(jsonObject.getString("to"))) {
                    String actionMapFromKey = jsonObject.getString("from");
                    String actionMapToKey = jsonObject.getString("to");
//                    shellAction = actionMap.get(actionMapFromKey);
                    ShellActionBuilder builder = ShellActionBuilder.create()
                            .withName(nodeName.get(actionMapToKey).toString() + actionMapToKey.replace("-", ""))
                            .withResourceManager("${resourceManager}")
                            .withNameNode("${nameNode}")
                            .withConfigProperty("mapred.job.queue.name", "${queueName}")
                            .withExecutable("${EXEC" + actionMapToKey.replace("-", "") + "}")
                            .withFile("${nameNode}/${rootDir}/${EXEC" + actionMapToKey.replace("-", "") + "}#${EXEC" + actionMapToKey.replace("-", "") + "}")
                            .withoutFile("${nameNode}/${rootDir}/${EXEC" + actionMapFromKey.replace("-", "") + "}#${EXEC" + actionMapFromKey.replace("-", "") + "}");
//                    if (isCoordinatorJob)
//                        builder .withErrorHandler(ErrorHandler.buildAsErrorHandler(actionBuilder));
//                    else
                    builder.withoutErrorHandler();
                    for (Object o : dependence) {
                        JSONObject jsonObject2 = JSONObject.parseObject(o.toString());
                        if (jsonObject2.getString("to").equals(actionMapToKey)) {
                            builder.withParent(actionMap.get(jsonObject2.getString("from")));
                        }
                    }
                    shellAction = builder.build();
                    actionMap.put(actionMapToKey, shellAction);
                }
            }
        }
//        if(isCoordinatorJob){
//            ShellActionBuilder builder = ShellActionBuilder.createFromExistingAction(shellAction)
//                    .withParent(shellAction)
//                    .withName("restTwo")
//                    .withCaptureOutput(null)
//                    .withExecutable("${EXEC0}")
//                    .withFile("${nameNode}/${rootDir}/${EXEC0}#${EXEC0}")
//                    .withoutErrorHandler();
//            shellAction = builder.build();
//        }

        Workflow workflow = new WorkflowBuilder()
                .withName(jobId)
                .withDagContainingNode(shellAction)
                .build();

        return workflow;
    }




    public Workflow creatAllShell(Set<JSONObject> allLinkedSet, String jobId,JobNodeConfig jobNodeConfig) {
        Integer reTryInterval = null,reTryMax = null;
        if(null != jobNodeConfig && Objects.equals(1,jobNodeConfig.getSchedule_type()) && Objects.equals(1,jobNodeConfig.getIsRetry())){
            reTryInterval = jobNodeConfig.getReTryInterval();
            reTryMax = jobNodeConfig.getReTryMax();
        }
        Map<String, ShellAction> actionMap = new HashMap<>();
        //开始节点
        ShellActionBuilder startBuilder = builderStartOrEndAction(1);
        ShellAction shellAction = startBuilder.build();
        actionMap.put(JobType.ObjOf(0).getEnName() + "_0", shellAction);
        //存放每个节点的父节点集合
        Map<String,List<String>> dependence2 = new LinkedHashMap();
        allLinkedSet.forEach(d -> {
            if (dependence2.containsKey(d.getString("to"))) {
                List<String> fromNodes =  dependence2.get(d.getString("to"));
                fromNodes.add(d.getString("from"));
                dependence2.put(d.getString("to"), fromNodes);
            } else {
                List<String> fromNodes = new ArrayList();
                fromNodes.add(d.getString("from"));
                dependence2.put(d.getString("to"), fromNodes);
            }
        });
        //生成每个节点action
        while (actionMap.size() != dependence2.size() + 1) {
            for (JSONObject d : allLinkedSet) {
                List<String> fromNodes =  dependence2.get(d.getString("to"));
                Boolean flag = true;
                //判断该节点的所有父节点是否都已经生成action，没有就返回false
                for (String f : fromNodes) {
                    if (!actionMap.containsKey(f)) {
                        flag = false;
                    }
                }
                //生成 action 的前提是所有父节点都已经生成，且该节点未曾生成
                if (flag && !actionMap.containsKey(d.getString("to"))) {
                    String actionMapFromKey = d.getString("from");
                    String actionMapToKey = d.getString("to");
                    ShellActionBuilder builder = ShellActionBuilder.create()
                            .withName(actionMapToKey)
                            .withResourceManager("${resourceManager}")
                            .withNameNode("${nameNode}")
                            .withConfigProperty("mapred.job.queue.name", "${queueName}")
                            .withExecutable("${EXEC" + actionMapToKey + "}")
                            .withFile("${nameNode}/${rootDir}/${EXEC" + actionMapToKey + "}#${EXEC" + actionMapToKey + "}")
                            .withoutFile("${nameNode}/${rootDir}/${EXEC" + actionMapFromKey + "}#${EXEC" + actionMapFromKey + "}")
                            .withCaptureOutput(Boolean.TRUE);
                    if(null != reTryInterval){
                        builder.withRetryInterval(reTryInterval);
                    }
                    if(null != reTryMax){
                        builder.withRetryMax(reTryMax);
                    }
                    builder.withoutErrorHandler();
                    for (JSONObject o : allLinkedSet) {
                        if (o.getString("to").equals(actionMapToKey)) {
                            builder.withParent(actionMap.get(o.getString("from")));
                            builder.withArgument("${wf:actionData('Start_0').depOOzieId}");
                        }
                    }
                    shellAction = builder.build();
                    actionMap.put(actionMapToKey, shellAction);
                }
            }
        }
        Workflow workflow = new WorkflowBuilder()
                .withName(jobId)
                .withDagContainingNode(shellAction)
                .build();

        return workflow;
    }


    /***
     * 生成workFlow.xml
     * @param linkedNodeList  同一个节点对应的父节点
     * @param jobId    任务id
     * @return
     */
    public Workflow creatJobNodeShell(List<List<JobNodeInfoDto>> linkedNodeList, Integer jobId,JobNodeConfig jobNodeConfig) {
        //节点连线和节点的配置
        if (CollectionUtil.isNotEmpty(linkedNodeList)) {
            //按照连线，拼装数据
            Set<JSONObject> allLinkedSet = new HashSet<>();
            for (List<JobNodeInfoDto> jobNodeInfoDtos : linkedNodeList) {
                for(int i = 1; i<jobNodeInfoDtos.size();i++){
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("from",jobNodeInfoDtos.get(i-1).getWorkFlowNodeName());
                    jsonObject.put("to",jobNodeInfoDtos.get(i).getWorkFlowNodeName());
                    allLinkedSet.add(jsonObject);
                }
                //结束节点
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("from",jobNodeInfoDtos.get(jobNodeInfoDtos.size()-1).getWorkFlowNodeName());
                jsonObject.put("to",JobType.ObjOf(5).getEnName() + "_0");
                allLinkedSet.add(jsonObject);
            }
            return creatAllShell(allLinkedSet,jobId.toString(),jobNodeConfig);
        }
        return null;
    }

    /***
     * 生成workFlow.xml
     * @param linkedList  同一个节点对应的父节点
     * @param workMenuDepId    任务流依赖id
     * @return
     */
    public Workflow creatShell(List<List<JobInfoDto>> linkedList, Integer workMenuDepId,JobNodeConfig jobNodeConfig) {
        //节点连线和节点的配置
        if (CollectionUtil.isNotEmpty(linkedList)) {
            //按照连线，拼装数据
            Set<JSONObject> allLinkedSet = new HashSet<>();
            for (List<JobInfoDto> jobInfoDtos : linkedList) {
                for(int i = 1; i<jobInfoDtos.size();i++){
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("from",jobInfoDtos.get(i-1).getWorkFlowNodeName());
                    jsonObject.put("to",jobInfoDtos.get(i).getWorkFlowNodeName());
                    allLinkedSet.add(jsonObject);
                }
                //结束节点
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("from",jobInfoDtos.get(jobInfoDtos.size()-1).getWorkFlowNodeName());
                jsonObject.put("to",JobType.ObjOf(5).getEnName() + "_0");
                allLinkedSet.add(jsonObject);
            }
            return creatAllShell(allLinkedSet,workMenuDepId.toString(),jobNodeConfig);
        }
        return null;
    }

    /***
     * 生成对应的开始节点和结束节点
     * @param level            1：开始节点  2：结束节点
     * @return action
     */
    private ShellActionBuilder builderStartOrEndAction(int level) {

        if (1 == level) {
            //开始节点
            ShellActionBuilder startBuilder = ShellActionBuilder.create()
                    .withName(JobType.ObjOf(0).getEnName() + "_0")
                    .withResourceManager("${resourceManager}")
                    .withNameNode("${nameNode}")
                    .withConfigProperty("mapred.job.queue.name", "${queueName}")
                    .withExecutable("${EXEC" + JobType.ObjOf(0).getEnName() + "_0}")
                    .withArgument("${wf:id()}")
                    .withFile("${nameNode}/${rootDir}/${EXEC" + JobType.ObjOf(0).getEnName() + "_0}#${EXEC" + JobType.ObjOf(0).getEnName() + "_0}")
                    .withCaptureOutput(true);
            startBuilder.withoutErrorHandler();
            return startBuilder;
        }
        if (2 == level) {
            //结束节点
            ShellActionBuilder endBuilder = ShellActionBuilder.create()
                    .withName(JobType.ObjOf(5).getEnName() + "_0")
                    .withResourceManager("${resourceManager}")
                    .withNameNode("${nameNode}")
                    .withConfigProperty("mapred.job.queue.name", "${queueName}")
                    .withExecutable("${EXEC" + JobType.ObjOf(5).getEnName() + "_0}")
                    .withFile("${nameNode}/${rootDir}/${EXEC" + JobType.ObjOf(5).getEnName() + "_0}#${EXEC" + JobType.ObjOf(5).getEnName() + "_0}")
                    .withCaptureOutput(true);
            endBuilder.withoutErrorHandler();
            return endBuilder;
        }
        return null;
    }

    public Workflow creatJobNodeHaveConditionShell(List<List<JobNodeInfoDto>> linkedNodeList, Integer jobId, JobNodeConfig jobNodeConfig) {
        //节点连线和节点的配置
        if (CollectionUtil.isNotEmpty(linkedNodeList)) {
            //按照连线，拼装数据和对应的路由数据
            Set<JSONObject> allLinkedSet = new HashSet<>();
            List<JSONObject> allLinkedLists = new ArrayList<>();
            Set<JSONObject> allErrorBuilders = new HashSet<>();
            for (List<JobNodeInfoDto> jobNodeInfoDtos : linkedNodeList) {
                //目前失败的路由节点下不能有依赖的节点
                //逆向查找对应的是否配置错误路由条件，如果配置挑选出来，并且先生成对应的shellAction。好方便生成对应的workflow
                Boolean flage = Boolean.FALSE;
                for(int i = 1; i<jobNodeInfoDtos.size();i++){
                    JobNodeInfoDto jobNodeInfoDto = jobNodeInfoDtos.get(i);
                    JobNodeInfoDto upJobNodeInfoDto = jobNodeInfoDtos.get(i-1);
                    Integer haveError = jobNodeInfoDto.getHaveError();
                    if(Objects.equals(haveError,1)){
                        //挑选出来当前的上游节点是成功到这个还是失败到这个
                        flage = Boolean.TRUE;
                        Set<Integer> errorUpNodes = jobNodeInfoDto.getErrorUpNodes();
                        if(CollectionUtil.isNotEmpty(errorUpNodes)){
                            JSONObject jsonObject = allLinkedLists.stream().filter(o -> Objects.equals(o.getString("to"), upJobNodeInfoDto.getWorkFlowNodeName())).findAny().orElse(null);
                            if(errorUpNodes.contains(upJobNodeInfoDto.getId())){
                                jsonObject.put("errorShellAction",createJobNodeHaveConditionAndErrorShell(upJobNodeInfoDto,jobNodeInfoDto,allErrorBuilders,jobId,jobNodeConfig));
                            }
                            //判断是否是全部失败路由到下一个节点
                            allErrorBuilders.add(jsonObject);
                        }
                        break;
                    }else{
                        Boolean isUpdate = Boolean.FALSE;
                        JSONObject jsonObject = null;
                        JSONObject olderObj = null;
                        if(CollectionUtil.isNotEmpty(allLinkedLists)){
                            for (JSONObject obj : allLinkedLists) {
                                String from = obj.getString("from");
                                String to = obj.getString("to");
                                if(upJobNodeInfoDto.getWorkFlowNodeName().equals(from) && jobNodeInfoDto.getWorkFlowNodeName().equals(to)){
                                    jsonObject = obj;
                                    olderObj = obj;
                                    isUpdate = Boolean.TRUE;
                                }
                            }
                        }
                        if(null == jsonObject){
                            jsonObject = new JSONObject();
                        }
                        jsonObject.put("from",upJobNodeInfoDto.getWorkFlowNodeName());
                        jsonObject.put("to",jobNodeInfoDto.getWorkFlowNodeName());
                        //to 对应的是否是虚拟节点---是需要传参的  暂时按照virCount字段来传递参数
                        jsonObject.put("virType",jobNodeInfoDto.getVirType());
                        if(null != jobNodeInfoDto.getVirType()){
                            //设置对应的传递的参数问题
                            if(Objects.equals(2,jobNodeInfoDto.getVirType())){
                                jsonObject.put("virParam","virCount");
                            }
                        }
                        //to 对应的是否配置了路由条件---是需要知道表达式的
                        jsonObject.put("haveCondition",jobNodeInfoDto.getHaveCondition());
                        jsonObject.put("haveError",jobNodeInfoDto.getHaveError());
                        if(Objects.equals(jobNodeInfoDto.getHaveCondition(),1)){
                            //设置对应的路由条件表达式
                            jsonObject.put("routeCondit",pingRouteCondit(jobNodeInfoDto,upJobNodeInfoDto.getWorkFlowNodeName()));
                        }
                        //先删除以前的
                        if(isUpdate){
                            allLinkedLists.remove(olderObj);
                        }
                        allLinkedLists.add(jsonObject);
                    }
                }
                //结束节点
                if(!flage){
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("from",jobNodeInfoDtos.get(jobNodeInfoDtos.size()-1).getWorkFlowNodeName());
                    jsonObject.put("to",JobType.ObjOf(5).getEnName() + "_0");
                    allLinkedLists.add(jsonObject);
                }
            }
            if(CollectionUtil.isNotEmpty(allLinkedLists)){
                allLinkedSet.addAll(allLinkedLists);
            }
            return creatAllHaveConditionShell(allLinkedSet,jobId.toString(),jobNodeConfig);
        }
        return null;
    }

    private ShellActionBuilder createJobNodeHaveConditionAndErrorShell(JobNodeInfoDto upJobNodeInfoDto, JobNodeInfoDto jobNodeInfoDto, Set<JSONObject> allErrorBuilders, Integer jobId, JobNodeConfig jobNodeConfig) {
        if(CollectionUtil.isNotEmpty(allErrorBuilders)){
            JSONObject jsonObject = allErrorBuilders.stream().filter(o -> Objects.equals(o.getString("workFlowNodeName"), jobNodeInfoDto.getWorkFlowNodeName())).findAny().orElse(null);
            if(null != jsonObject){
                return (ShellActionBuilder)jsonObject.get("workFlowNodeName");
            }
        }
        //重新生成，并且存起来
        ShellActionBuilder builder = ShellActionBuilder.create()
                .withName(jobNodeInfoDto.getWorkFlowNodeName())
                .withResourceManager("${resourceManager}")
                .withNameNode("${nameNode}")
                .withConfigProperty("mapred.job.queue.name", "${queueName}")
                .withExecutable("${EXEC" + jobNodeInfoDto.getWorkFlowNodeName() + "}")
                .withFile("${nameNode}/${rootDir}/${EXEC" + jobNodeInfoDto.getWorkFlowNodeName() + "}#${EXEC" + jobNodeInfoDto.getWorkFlowNodeName() + "}")
                .withoutFile("${nameNode}/${rootDir}/${EXEC" + upJobNodeInfoDto.getWorkFlowNodeName() + "}#${EXEC" + upJobNodeInfoDto.getWorkFlowNodeName() + "}");
        builder.withoutErrorHandler();
        builder.withCaptureOutput(Boolean.TRUE);
        return builder;
    }

    private String pingRouteCondit(JobNodeInfoDto jobNodeInfoDto,String upNodeWorkFlowName) {
        if(null != jobNodeInfoDto){
            List<JobNodeLayConfigDto> jobNodeLayConfigDtoList = jobNodeInfoDto.getJobNodeLayConfigDtoList();
            if(CollectionUtil.isNotEmpty(jobNodeLayConfigDtoList)){
                String[] split = upNodeWorkFlowName.split("_");
                if(null != split && split.length >= 2){
                    for (JobNodeLayConfigDto jobNodeLayConfigDto : jobNodeLayConfigDtoList) {
                        if(null != jobNodeLayConfigDto.getUpNodeId() && split[1].contains(String.valueOf(jobNodeLayConfigDto.getUpNodeId()))){
                            return ".virCount " + change(jobNodeLayConfigDto.getOperationNamme()) + " " + jobNodeLayConfigDto.getConditionValue();
                        }
                    }
                }
            }
        }
        return null;
    }

    private String change(String operationNamme) {
        if(StringUtils.isEmpty(operationNamme)){
            return null;
        }
        if("!=".equals(operationNamme.trim())){
            return "ne";
        }
        if("=".equals(operationNamme.trim())){
            return "eq";
        }
        if(">".equals(operationNamme.trim())){
            return "gt";
        }
        if("<".equals(operationNamme.trim())){
            return "lt";
        }
        if(">=".equals(operationNamme.trim())){
            return "ge";
        }
        if("<=".equals(operationNamme.trim())){
            return "le";
        }
        return null;
    }

    private Workflow creatAllHaveConditionShell(Set<JSONObject> allLinkedSet, String jobId, JobNodeConfig jobNodeConfig) {

        Integer reTryInterval = null,reTryMax = null;
        if(null != jobNodeConfig && Objects.equals(1,jobNodeConfig.getSchedule_type()) && Objects.equals(1,jobNodeConfig.getIsRetry())){
            reTryInterval = jobNodeConfig.getReTryInterval();
            reTryMax = jobNodeConfig.getReTryMax();
        }
        Map<String, ShellAction> actionMap = new HashMap<>();
        //开始节点
        ShellActionBuilder startBuilder = builderStartOrEndAction(1);
        ShellAction shellAction = startBuilder.build();
        actionMap.put(JobType.ObjOf(0).getEnName() + "_0", shellAction);
        //存放每个节点的父节点集合
        Map<String,List<String>> dependence2 = new LinkedHashMap();
        allLinkedSet.forEach(d -> {
            if (dependence2.containsKey(d.getString("to"))) {
                List<String> fromNodes =  dependence2.get(d.getString("to"));
                fromNodes.add(d.getString("from"));
                dependence2.put(d.getString("to"), fromNodes);
            } else {
                List<String> fromNodes = new ArrayList();
                fromNodes.add(d.getString("from"));
                dependence2.put(d.getString("to"), fromNodes);
            }
        });
        //生成每个节点action
        while (actionMap.size() != dependence2.size() + 1) {
            for (JSONObject d : allLinkedSet) {
                List<String> fromNodes =  dependence2.get(d.getString("to"));
                Boolean flag = true;
                //判断该节点的所有父节点是否都已经生成action，没有就返回false
                for (String f : fromNodes) {
                    if (!actionMap.containsKey(f)) {
                        flag = false;
                    }
                }
                //生成 action 的前提是所有父节点都已经生成，且该节点未曾生成
                if (flag && !actionMap.containsKey(d.getString("to"))) {
                    String actionMapFromKey = d.getString("from");
                    String actionMapToKey = d.getString("to");
                    ShellActionBuilder builder = ShellActionBuilder.create()
                            .withName(actionMapToKey)
                            .withResourceManager("${resourceManager}")
                            .withNameNode("${nameNode}")
                            .withConfigProperty("mapred.job.queue.name", "${queueName}")
                            .withExecutable("${EXEC" + actionMapToKey + "}")
                            .withFile("${nameNode}/${rootDir}/${EXEC" + actionMapToKey + "}#${EXEC" + actionMapToKey + "}")
                            .withoutFile("${nameNode}/${rootDir}/${EXEC" + actionMapFromKey + "}#${EXEC" + actionMapFromKey + "}");
                    if(null != reTryInterval){
                        builder.withRetryInterval(reTryInterval);
                    }
                    if(null != reTryMax){
                        builder.withRetryMax(reTryMax);
                    }
                    //错误路由
                    Object errorShellAction = null;
                    Set<JSONObject> from = allLinkedSet.stream().filter(o -> Objects.equals(o.getString("to"), actionMapToKey)).collect(Collectors.toSet());
                    if(CollectionUtil.isNotEmpty(from)){
                        for (JSONObject jsonObject : from) {
                            errorShellAction = jsonObject.get("errorShellAction");
                            if(null != errorShellAction){
                                break;
                            }
                        }
                    }
                    if(null != errorShellAction){
                        ShellActionBuilder errShellAction = (ShellActionBuilder) errorShellAction;
                        builder.withErrorHandler(ErrorHandler.buildAsErrorHandler(errShellAction));
                    }else{
                        builder.withoutErrorHandler();
                    }
                    builder.withCaptureOutput(Boolean.TRUE);
                    for (JSONObject o : allLinkedSet) {
                        if (o.getString("to").equals(actionMapToKey)) {
                            //判断是否有路由条件
                            Integer haveCondition = o.getInteger("haveCondition");
                            if(null != haveCondition && haveCondition == 1){
                                builder.withParentWithCondition(actionMap.get(o.getString("from")),"${wf:actionData('"+actionMapFromKey+"')" + o.getString("routeCondit") + "}");
                            } else {
                                Integer virType = o.getInteger("virType");
                                if(Objects.equals(1,virType)){
                                    builder.withParentDefaultConditional(actionMap.get(o.getString("from")));
                                }else if(Objects.equals(2,virType)){
                                    builder.withArgument("${wf:actionData('"+actionMapFromKey+"').virCount}");
                                    builder.withParent(actionMap.get(o.getString("from")));
                                }else {
                                    builder.withParent(actionMap.get(o.getString("from")));
                                }
                            }
                        }
                    }
                    shellAction = builder.build();
                    actionMap.put(actionMapToKey, shellAction);
                }
            }
        }
        Workflow workflow = new WorkflowBuilder()
                .withName(jobId)
                .withDagContainingNode(shellAction)
                .build();

        return workflow;
    }
}
